package com.c2b.algorithm.leetcode.base.monotone_stack;

import com.c2b.algorithm.leetcode.base.Printer;

import java.util.ArrayDeque;
import java.util.Deque;

/**
 * <a href="https://leetcode.cn/problems/final-prices-with-a-special-discount-in-a-shop/">商品折扣后的最终价格(Final Prices With a Special Discount in a Shop)</a>
 * <p>给你一个数组 prices ，其中 prices[i] 是商店里第 i 件商品的价格。</p>
 * <p>商店里正在进行促销活动，如果你要买第 i 件商品，那么你可以得到与 prices[j] 相等的折扣，其中 j 是满足 j > i 且 prices[j] <= prices[i] 的 最小下标 ，如果没有满足条件的 j ，你将没有任何折扣。</p>
 * <p>请你返回一个数组，数组中第 i 个元素是折扣后你购买商品 i 最终需要支付的价格。</p>
 * <p>
 * <b>示例：</b>
 * <pre>
 * 示例 1：
 *      输入：prices = [8,4,6,2,3]
 *      输出：[4,2,4,2,3]
 *      解释：
 *          商品 0 的价格为 price[0]=8 ，你将得到 prices[1]=4 的折扣，所以最终价格为 8 - 4 = 4 。
 *          商品 1 的价格为 price[1]=4 ，你将得到 prices[3]=2 的折扣，所以最终价格为 4 - 2 = 2 。
 *          商品 2 的价格为 price[2]=6 ，你将得到 prices[3]=2 的折扣，所以最终价格为 6 - 2 = 4 。
 *          商品 3 和 4 都没有折扣。
 *
 * 示例 2：
 *      输入：prices = [1,2,3,4,5]
 *      输出：[1,2,3,4,5]
 *      解释：在这个例子中，所有商品都没有折扣。
 *
 * 示例 3：
 *      输入：prices = [10,1,1,6]
 *      输出：[9,0,1,6]
 * </pre>
 * </p>
 * <p>
 * <b>提示：</b>
 * <ul>
 *     <li>1 <= prices.length <= 500</li>
 *     <li>1 <= prices[i] <= 10^3</li>
 * </ul>
 * </p>
 *
 * @author c2b
 * @since 2023/11/4 15:39
 */
public class LC01475FinalPricesWithSpecialDiscountInShop_S {

    static class Solution {
        public int[] finalPrices(int[] prices) {
            // 单调递减栈
            Deque<Integer> stack = new ArrayDeque<>();
            int[] ans = new int[prices.length];
            // 8,4,6,2,3    stack
            //      3         3
            //      2         2
            //      6         2 6
            //      4         2 4
            //      8         2 4 8
            for (int i = prices.length - 1; i >= 0; i--) {
                int currPrice = prices[i];
                while (!stack.isEmpty() && currPrice < stack.peekLast()) {
                    stack.pollLast();
                }
                ans[i] = stack.isEmpty() ? currPrice : currPrice - stack.peekLast();
                stack.offerLast(currPrice);
            }
            return ans;
        }

        public int[] finalPrices2(int[] prices) {
            // 单调递减栈
            Deque<Integer> stack = new ArrayDeque<>();
            for (int i = 0; i < prices.length; i++) {
                int currPrice = prices[i];
                while (!stack.isEmpty() && currPrice <= prices[stack.peekLast()]) {
                    Integer idx = stack.pollLast();
                    prices[idx] = prices[idx] - currPrice;
                }
                stack.offerLast(i);
            }
            return prices;
        }
    }

    public static void main(String[] args) {
        Solution solution = new Solution();
        Printer.printArrayInt(solution.finalPrices(new int[]{8, 4, 6, 2, 3}));
        Printer.printArrayInt(solution.finalPrices(new int[]{1, 2, 3, 4, 5}));
        Printer.printArrayInt(solution.finalPrices(new int[]{10, 1, 1, 6}));
    }
}
